package com.liaowei.post.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liaowei.common.Constants;
import com.liaowei.common.ErrorCode;
import com.liaowei.exception.CustomerException;
import com.liaowei.model.domain.Post;
import com.liaowei.model.domain.PostUser;
import com.liaowei.model.domain.SpecialColumn;
import com.liaowei.model.vo.PostVO;
import com.liaowei.post.mapper.PostMapper;
import com.liaowei.post.mapper.PostUserMapper;
import com.liaowei.post.mapper.SpecialColumnMapper;
import com.liaowei.post.model.param.PostPageParam;
import com.liaowei.post.model.param.SavePostParam;
import com.liaowei.post.openfeign.PostCommentClient;
import com.liaowei.post.openfeign.UserClient;
import com.liaowei.post.service.PostService;
import com.liaowei.post.service.SpecialColumnService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author LindaMan
 * @description 针对表【wy_post(帖子表)】的数据库操作Service实现
 * @createDate 2023-05-11 08:31:59
 */
@Service
@RequiredArgsConstructor
public class PostServiceImpl extends ServiceImpl<PostMapper, Post>
        implements PostService {

    private final PostMapper postMapper;
    private final SpecialColumnMapper specialColumnMapper;
    private final SpecialColumnService specialColumnService;
    private final PostUserMapper postUserMapper;
    private final PostCommentClient postCommentClient;
    private final UserClient userClient;


    // 校验是否是认证用户
    public void matchAuthUser(long userId, long loginId) {
        if (userId != loginId)
            throw new CustomerException(ErrorCode.NO_AUTHORITY);
    }

    // 校验是否是合法专栏
    public void matchColumn(Long columnId) {
        // 根据专栏id查询是否存在该专栏
        LambdaUpdateWrapper<SpecialColumn> columnWrapper = Wrappers.lambdaUpdate(SpecialColumn.class)
                .eq(SpecialColumn::getId, columnId)
                .eq(SpecialColumn::getStatus, 1);
        SpecialColumn column = specialColumnMapper.selectOne(columnWrapper);
        if (BeanUtil.isEmpty(column))
            throw new CustomerException(Constants.PARAM_ERROR, "请输入合法的专栏");
    }

    // post转换为postVO
    public PostVO toPostVO(Post post) {
        long postId = post.getId(); // 获取postId
        // 封装PostVO
        PostVO postVO = new PostVO();
        BeanUtil.copyProperties(post, postVO);
        // 封装其他属性
        PostVO temp = postMapper.selectPostVOById(postId);
        postVO.setNickname(temp.getNickname());
        postVO.setStar(temp.getStar());
        postVO.setAccessNumber(temp.getAccessNumber());
        postVO.setSpecialColumnName(temp.getSpecialColumnName());

        // 封装commentList，无需封装只需要前端调用文章评论服务的接口即可

        return postVO;
    }


    /**
     * 查询帖子相关推荐列表
     *
     * @param userId 用户id
     * @return List<PostVO>
     */
    @Override
    public List<PostVO> searchRecommendPostList(Long userId) {
        // 判断userId是否为空
        if (BeanUtil.isNotEmpty(userId)) {
            // 这里无需判断用户是否合法，不存在安全性问题，只做推荐
            // 查询最近访问的帖子所属的专栏
            List<SpecialColumn> accessColList = specialColumnService.searchColumnListByUserId(userId);

            if (accessColList.size() > 0){
                // 获取访问过的专栏id
                List<Long> colIdList = accessColList.stream().map(SpecialColumn::getId).collect(Collectors.toList());

                // 专栏id去重
                List<Long> distinctColIdList = colIdList.stream().distinct().collect(Collectors.toList());

                // 根据专栏id查询帖子 -- 取前5个
                List<Post> postList = postMapper.selectList(Wrappers.lambdaQuery(Post.class)
                        .in(Post::getSpecialColumnId, distinctColIdList))
                        .stream().limit(5).collect(Collectors.toList());

                // 转换VO
                List<PostVO> postVOList = postList.stream().map(this::toPostVO).collect(Collectors.toList());

                return postVOList;
            }
        }
        // 用户未登录，那么按照访问量查询
        List<PostVO> hotList = this.searchHotPostList();
        //  取前5条
        return hotList.stream().limit(5).collect(Collectors.toList());
    }

    /**
     * 查询自己发布的帖子
     *
     * @param userId 用户id
     * @param title  标题
     * @return List<Post>
     */
    @Override
    public List<Post> searchOwnPostList(Long userId, String title) {
        // 检验是否合法用户
//        long loginId = StpUtil.getLoginIdAsLong();
//        matchAuthUser(userId,loginId);

        // 根据title模糊查询帖子列表
        LambdaQueryWrapper<Post> wrapper = Wrappers.lambdaQuery(Post.class)
                .like(Post::getTitle, title).eq(Post::getUserId, userId);
        List<Post> postList = postMapper.selectList(wrapper);

        return Optional.ofNullable(postList).orElse(new ArrayList<>());
    }

    /**
     * 查询贴吧热议榜
     *
     * @return List<Post>
     */
    @Override
    public List<PostVO> searchHotPostList() {
        List<PostVO> postList = postMapper.selectHotPostList();
        return Optional.ofNullable(postList).orElse(new ArrayList<>());
    }

    /**
     * 通过标题分页查询帖子列表
     *
     * @param title    搜索标题
     * @param pageNum  当前页
     * @param pageSize 分页大小
     * @return IPage<Post>
     */
    @Override
    public IPage<Post> searchPostPageByTitle(String title, int pageNum, int pageSize) {
        // 构造分页构造器
        IPage<Post> page = new Page<>(pageNum, pageSize);

        // 构造查询构造器
        if (title == null)
            title = "";
        LambdaQueryWrapper<Post> wrapper = Wrappers.lambdaQuery(Post.class).like(Post::getTitle, title)
                .orderByDesc(Post::getCreateTime);

        // 分页查询
        postMapper.selectPage(page, wrapper);

        // 返回结果
        return page;
    }

    /**
     * 通过id列表查询帖子列表
     *
     * @param postIds 帖子id列表
     * @return List<Post> 帖子列表
     */
    @Override
    public List<Post> searchPostListByIds(List<Long> postIds) {
        return Optional.ofNullable(this.listByIds(postIds)).orElse(new ArrayList<>());
    }

    /**
     * 根据userId查询帖子数量
     *
     * @param userId 用户id
     * @return 总条数
     */
    @Override
    public Long searchCountOfPostByUserId(Long userId) {
        return postMapper.selectCount(Wrappers.lambdaQuery(Post.class).eq(Post::getUserId, userId));
    }

    /**
     * 删除帖子
     *
     * @param postId 帖子id
     * @param userId 用户id
     * @return 提示信息
     */
    @Transactional
    @Override
    public String removePostByIdAndUserId(Long postId, Long userId) {
        // 校验用户
        if (userId != 1) {
            // 不是管理员就需要校验是否认证
            Long loginId = Long.parseLong(StpUtil.getLoginId().toString());
            matchAuthUser(userId, loginId);
        }

        try {
            // 删除帖子用户
            LambdaUpdateWrapper<PostUser> deleteAUWrapper = Wrappers.lambdaUpdate(PostUser.class)
                    .eq(PostUser::getPostId, postId);
            postUserMapper.delete(deleteAUWrapper);

            // 删除评论
            postCommentClient.deleteComment(postId, userId);

            // 删除用户的浏览帖子记录
            userClient.deletePostHistoryByUserIdAndPostId(userId, postId);

            // 删除帖子
            postMapper.deleteById(postId);
        } catch (Exception e) {
            throw new CustomerException(ErrorCode.SYSTEM_ERROR);
        }

        return "删除成功";
    }

    /**
     * 根据id查询帖子
     *
     * @param postId 帖子id
     * @return 帖子信息
     */
    @Override
    public Post searchPostVoById(Long postId) {
        return postMapper.selectById(postId);
    }

    /**
     * 查询帖子详细信息以及和用户的状态
     *
     * @param postId 帖子id
     * @param userId 当前用户id
     * @return
     */
    @Override
    public PostVO searchPostVo(Long postId, Long userId) {
        // 根据id查询文章
        Post post = postMapper.selectById(postId);

        // 判断文章是否存在
        if (BeanUtil.isEmpty(postId))
            throw new CustomerException(Constants.PARAM_ERROR, "不存在该帖子");

        // 封装ArticleVO
        PostVO postVO = toPostVO(post);
        // 额外封装参数
        // collectStatus
        int collectStatus = postUserMapper.selectCollectStatusByUserId(userId);
        postVO.setCollectStatus(collectStatus);

        // 返回结果
        return postVO;
    }

    /**
     * 条件分页查询帖子列表
     *
     * @param pageParam 分页查询参数
     * @return IPage<Post>
     */
    @Override
    public IPage<Post> searchPostPage(PostPageParam pageParam) {
        // 获取分页参数
        int pageNum = pageParam.getPageParam().getPageNum();
        int pageSize = pageParam.getPageParam().getPageSize();

        // 构造分页构造器
        IPage<Post> page = new Page<>(pageNum, pageSize);

        // 分页参数预处理
        pageNum = (pageNum - 1) * pageSize;
        pageParam.getPageParam().setPageNum(pageNum);

        // 分页查询
        List<Post> records = postMapper.selectPostPage(pageParam);
        int total = postMapper.selectPostCount(pageParam);

        // 封装page
        page.setRecords(records);
        page.setTotal(total);

        // 返回结果
        return page;
    }

    /**
     * 保存发帖信息
     *
     * @param postParam 保存发帖参数
     * @return 提示信息
     */
    @Transactional
    @Override
    public String savePost(SavePostParam postParam) {
        // 参数获取
        long loginId = Long.parseLong(StpUtil.getLoginId().toString()); // 获取登录id
        Long userId = postParam.getUserId(); // 发帖人id
        Long createBy = postParam.getCreateBy(); // 创建人
        Long updateBy = postParam.getUpdateBy(); // 修改人
        Long columnId = postParam.getSpecialColumnId(); // 专栏id

        // 对参数进行二次校验
        // 用户校验
        matchAuthUser(userId, loginId);
        matchAuthUser(createBy, loginId);
        if (updateBy != 1) {
            // 修改人必须为管理员或者是本人
            matchAuthUser(updateBy, loginId);
        }
        // 专栏校验
        matchColumn(columnId);

        // 封装帖子
        Post post = new Post();
        post.setTitle(postParam.getTitle());
        post.setUserId(userId);
        post.setSpecialColumnId(columnId);
        post.setCoverImage(postParam.getCoverImage());
        post.setCreateBy(createBy);
        post.setUpdateBy(updateBy);

        try {
            // 判断id是否存在
            if (BeanUtil.isEmpty(postParam.getId())) {
                // 无id，新增
                postMapper.insert(post);

            } else {
                // 有id，修改
                post.setId(postParam.getId());
                post.setUpdateTime(new Date());
                postMapper.updateById(post);
            }
        } catch (Exception e) {
            throw new CustomerException(ErrorCode.SYSTEM_ERROR);
        }

        // 返回提示信息
        return "保存成功";
    }
}




